<template>
    <div>
        <el-card>
            <el-form :inline="true" class="form">
                <el-form-item label="用户搜索" style="margin: 0;">
                    <el-input placeholder="请输入想要搜索的用户名关键字" style="width: 15rem;" v-model="keyword"></el-input>
                </el-form-item>
                <el-form-item style="margin: 0;">
                    <el-button type="primary" size="default" :disabled="keyword ? false : true"
                        @click="search">搜索</el-button>
                    <el-button type="primary" size="default" @click="reset">重置</el-button>
                </el-form-item>
            </el-form>
        </el-card>
        <el-card style="margin: .625rem 0;">
            <el-button type="primary" size="default" @click="addUser" v-has="`btn.User.add`">添加用户</el-button>
            <el-button type="primary" size="default" :disabled="selectIdArr.length > 0 ? false : true"
                @click="deleteManyUser" v-has="`btn.User.remove`">批量删除</el-button>
            <el-table style="margin: .625rem 0;" border :data="userArr" @selection-change="selectChange">
                <el-table-column type="selection"></el-table-column>
                <el-table-column label="#" width="80px" type="index"></el-table-column>
                <el-table-column label="id" width="80px" prop="id"></el-table-column>
                <el-table-column label="用户姓名" prop="username"></el-table-column>
                <el-table-column label="用户名称" prop="name"></el-table-column>
                <el-table-column label="用户角色" prop="roleName"></el-table-column>
                <el-table-column label="创建时间" prop="createTime" show-overflow-tooltip></el-table-column>
                <el-table-column label="更新时间" prop="updateTime" show-overflow-tooltip></el-table-column>
                <el-table-column label="操作" width="280px">
                    <template #="{ row, $index }">
                        <el-button type="primary" size="small" icon="User" @click="setRole(row)"
                            v-has="`btn.User.assgin`">分配角色</el-button>
                        <el-button type="primary" size="small" icon="Edit" @click="updateUser(row)"
                            v-has="`btn.User.update`">编辑</el-button>
                        <el-popconfirm :title="`您确定删除${row.username}的账号吗？`" width="12rem" icon="Delete"
                            @confirm="deleteUser(row.id)">
                            <template #reference>
                                <el-button type="primary" size="small" icon="Delete"
                                    v-has="`btn.User.remove`">删除</el-button>
                            </template>
                        </el-popconfirm>
                    </template>
                </el-table-column>
            </el-table>
            <el-pagination :pager-count="9" v-model:current-page="pageNo" v-model:page-size="limit"
                :page-sizes="[3, 4, 5, 6]" :background="true" layout="prev, pager, next, jumper, ->, sizes, total"
                :total="total" @current-change="getHasUser" @size-change="sizeChange" />
        </el-card>
        <el-drawer v-model="drawer">
            <template #header>
                <h4>{{ userParams.id ? '更新用户' : '添加用户' }}</h4>
            </template>
            <template #default>
                <el-form :model="userParams" :rules="rules" ref="userForm">
                    <el-form-item label="用户姓名" prop="username">
                        <el-input placeholder="请输入用户的姓名" v-model="userParams.username"></el-input>
                    </el-form-item>
                    <el-form-item label="用户名称" prop="name">
                        <el-input placeholder="请输入用户的名称" v-model="userParams.name"></el-input>
                    </el-form-item>
                    <el-form-item label="用户密码" prop="password" v-if="!userParams.id">
                        <el-input placeholder="请输入用户的密码" v-model="userParams.password"></el-input>
                    </el-form-item>
                </el-form>
            </template>
            <template #footer>
                <el-button type="primary" size="default" @click="save">确认</el-button>
                <el-button type="primary" size="default" @click='cancel'>取消</el-button>
            </template>
        </el-drawer>
        <el-drawer v-model="drawer1">
            <template #header>
                <h4>分配角色</h4>
            </template>
            <template #default>
                <el-form>
                    <el-form-item label="用户姓名">
                        <el-input :placeholder="userParams.username" :disabled="true"></el-input>
                    </el-form-item>
                    <el-form-item label="角色列表">
                        <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate"
                            @change="handleCheckAllChange">全选</el-checkbox>
                        <el-checkbox-group v-model="checkedRole" @change="handleCheckedRoleChange">
                            <el-checkbox v-for="(role, index) in allRole" :key="index" :label="role" :value="role">
                                {{ role.roleName }}
                            </el-checkbox>
                        </el-checkbox-group>
                    </el-form-item>
                </el-form>
            </template>
            <template #footer>
                <el-button type="primary" size="default" @click="save1">确认</el-button>
                <el-button type="primary" size="default" @click='cancel1'>取消</el-button>
            </template>
        </el-drawer>
    </div>
</template>

<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { ref, onMounted, reactive, nextTick } from 'vue';
import { reqUserInfo, reqAddOrUpdateUser, reqAllRole, reqSetRole, reqDeleteUser, reqDeleteManyUser } from '@/api/acl/user';
import type { UserResponseData, Records, User, AllRole, AllRoleResponseData, SetRoleData } from '@/api/acl/user/type';

//当前页面的页码
let pageNo = ref<number>(1)
//每一页展示的数据项数量
let limit = ref<number>(3)
//存储已有用户的总数
let total = ref<number>(0)
//储存全部用户的数据
let userArr = ref<Records>([])
//定义响应式数据控制添加或编辑用户账号抽屉组件的显示与隐藏
let drawer = ref<boolean>(false)
//定义响应式数据控制分配角色抽屉组件的显示与隐藏
let drawer1 = ref<boolean>(false)
//收集用户信息的响应式数据
let userParams = reactive<User>({
    username: '',
    name: '',
    password: ''
})
//获取form组件实例
let userForm = ref<any>()
//是否全选
let checkAll = ref<boolean>(false)
//是否处于部分选择状态
let isIndeterminate = ref<boolean>(true)
//储存全部职位的数据
let allRole = ref<AllRole>([])
//当前用户已有的职位
let checkedRole = ref<AllRole>([])
//准备一个数组储存批量删除用户的id
let selectIdArr = ref<User[]>([])
//收集用户输入的关键字
let keyword = ref<string>('')

//获取用户信息数据
const getHasUser = async (pager = 1) => {
    pageNo.value = pager
    let result: UserResponseData = await reqUserInfo(pageNo.value, limit.value, keyword.value)
    if (result.code == 200) {
        total.value = result.data.total
        userArr.value = result.data.records
    }
}
//当下拉菜单发生变化的时候触发此方法
const sizeChange = () => {
    /*//首先让当前页码归1
    pageNo.value = 1
    */
    getHasUser()
}
//添加用户
const addUser = () => {
    drawer.value = true
    //清空数据
    Object.assign(userParams, {
        id: 0,
        username: '',
        name: '',
        password: ''
    })
    //清空错误提示信息
    nextTick(() => {
        userForm.value.clearValidate('username')
        userForm.value.clearValidate('name')
        userForm.value.clearValidate('password')
    })
}
//更新用户
const updateUser = (row: User) => {
    drawer.value = true
    //存储收集已有的账号信息
    Object.assign(userParams, row)
    //清空错误提示信息
    nextTick(() => {
        userForm.value.clearValidate('username')
        userForm.value.clearValidate('name')
    })
}
//添加与编辑保存按钮的回调
const save = async () => {
    //表单校验结果，结果通过再发请求，没有通过则不发请求
    await userForm.value.validate()
    drawer.value = false
    let result: any = await reqAddOrUpdateUser(userParams)
    if (result.code == 200) {
        ElMessage({
            type: 'success',
            message: userParams.id ? '更新成功' : '添加成功'
        })
        getHasUser(userParams.id ? pageNo.value : 1)
    } else {
        ElMessage({
            type: 'error',
            message: userParams.id ? '更新失败' : '添加失败'
        })
    }
    //浏览器自动刷新一次
    window.location.reload()
}
//添加与编辑取消按钮的回调
const cancel = () => {
    drawer.value = false
}
//分配角色保存按钮的回调
const save1 = async () => {
    let data: SetRoleData = {
        userId: (userParams.id as number),
        roleIdList: checkedRole.value.map(item => { return (item.id as number) })
    }
    drawer1.value = false
    let result: any = await reqSetRole(data)
    if (result.code == 200) {
        ElMessage({
            type: 'success',
            message: '分配职位成功'
        })
        getHasUser(pageNo.value)
    } else {
        ElMessage({
            type: 'error',
            message: '分配职位失败'
        })
    }
}
//分配角色取消按钮的回调
const cancel1 = () => {
    drawer1.value = false
}
//校验用户姓名回调函数
const validatorUsername = (rule: any, value: any, callback: any) => {
    if (value.trim().length >= 2 && value.trim().length <= 10) {
        callback()
    } else if (value.trim().length == 0 || 1) {
        callback(new Error('用户姓名至少包含两个汉字'))
    } else if (value.trim().length > 10)
        callback(new Error('用户姓名长度不合法，请输入正确的用户姓名'))
}
//校验用户名称回调函数
const validatorName = (rule: any, value: any, callback: any) => {
    if (value.trim().length >= 5 && value.trim().length <= 10) {
        callback()
    } else {
        callback(new Error('用户名称的长度至少为5位，至多为10位'))
    }
}
//校验用户密码回调函数
const validatorPassword = (rule: any, value: any, callback: any) => {
    if (value.trim().length >= 6 && value.trim().length <= 15) {
        callback()
    } else {
        callback(new Error('密码长度至少为6位，至多为15位'))
    }
}
//表单校验规则对象
const rules = {
    username: [{ require: true, trigger: 'blur', validator: validatorUsername }],
    name: [{ require: true, trigger: 'blur', validator: validatorName }],
    password: [{ require: true, trigger: 'blur', validator: validatorPassword }]
}
//分配角色按钮的回调
const setRole = async (row: User) => {
    Object.assign(userParams, row)
    let result: AllRoleResponseData = await reqAllRole((userParams.id as number))
    if (result.code == 200) {
        //储存全部的职位
        allRole.value = result.data.allRolesList
        //存储当前用户已有的职位
        checkedRole.value = result.data.assignRoles
    }
    if (checkedRole.value.length === 0 || checkedRole.value.length === allRole.value.length) {
        isIndeterminate.value = false
    } else if (checkedRole.value.length > 0 && checkedRole.value.length < allRole.value.length) {
        isIndeterminate.value = true
    }
    drawer1.value = true
}
//判断是否全选，如果是则将所有复选框选择，否则全不选
const handleCheckAllChange = (val: boolean) => {
    checkedRole.value = val ? allRole.value : []
    isIndeterminate.value = false
}
//判断是否处于部分选状态
const handleCheckedRoleChange = (value: string[]) => {
    const checkedCount = value.length
    checkAll.value = checkedCount === allRole.value.length
    isIndeterminate.value = checkedCount > 0 && checkedCount < allRole.value.length
}
//删除某一个用户账号的方法
const deleteUser = async (id: number) => {
    let result: any = await reqDeleteUser(id)
    if (result.code == 200) {
        ElMessage({
            type: 'success',
            message: '删除成功'
        })
        getHasUser(userArr.value.length > 1 ? pageNo.value : pageNo.value - 1)
    } else {
        ElMessage({
            type: 'error',
            message: '删除失败'
        })
    }
}
//table复选框勾选时会触发的事件
const selectChange = (value: any) => {
    selectIdArr.value = value
}
//批量删除用户账号的方法
const deleteManyUser = async () => {
    //整理批量删除的参数
    let idList: any = selectIdArr.value.map(item => { return item.id })
    //批量删除的请求
    let result: any = await reqDeleteManyUser(idList)
    if (result.code == 200) {
        ElMessage({
            type: 'success',
            message: '批量删除成功'
        })
        getHasUser(userArr.value.length > 1 ? pageNo.value : pageNo.value - 1)
    } else {
        ElMessage({
            type: 'error',
            message: '批量删除失败'
        })
    }
}
//搜索按钮的回调
const search = () => {
    //根据关键字获取用户相应数据
    getHasUser()
}
//重置按钮的回调
const reset = () => {
    //清空关键字
    keyword.value = ''
    //重新加载所有数据
    getHasUser()
}

onMounted(() => {
    getHasUser()
})
</script>

<style scoped lang="scss">
.form {
    height: 1.5rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
</style>